package br.com.velp.sudecap.mb.usuario;

import br.com.velp.sudecap.comum.BaseController;
import br.com.velp.sudecap.entidade.*;
import br.com.velp.sudecap.enumerator.PaginaEnum;
import br.com.velp.sudecap.enumerator.SistemaEnum;
import br.com.velp.sudecap.service.DireitoUsuarioService;
import br.com.velp.sudecap.service.GrupoUsuarioService;
import br.com.velp.sudecap.util.MensagemUtil;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import javax.faces.model.ListDataModel;
import javax.faces.model.SelectItem;
import org.lindbergframework.spring.scope.AccessScoped;
import org.primefaces.model.DualListModel;
import org.primefaces.model.SelectableDataModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

/**
 * <sumario>
 * <objetivo>"Rastreabilidade"</objetivo>
 * <autor>EDUARDO SANTOS DE OLIVEIRA</autor>
 * <versao>1.0.0.0</versao>
 * <data_criacao> 17.10.2012 </data_criacao>
 * <data_ultima_alteracao> N/A </data_ultima_alteracao>
 * <requisito_afetado> RF010.04 - Gerenciar de Grupo de Usuários </requisito_afetado>
 * <descricao> Managead Bean responsável por controlar as 
 *             operações inerentes a Grupos de Usuários </descricao>
 * </sumario>
 */
@Controller("grupoUsuarioMB")
@AccessScoped
public class GrupoUsuarioMB extends BaseController {

    public static final Long serialVersionUID = 1L;
    
    private Usuario usuarioSelecionado;
    private GrupoUsuario grupoSelecionado;
    private GrupoUsuarioDataModel grupoUsuarioDataModel;
    private UsuarioDataModel usuarioDataModel;
    private Usuario[] usuariosSelecionados;
    private List<DireitoSistema> direitos;
    private DualListModel<DireitoSistema> direitosSistema;
    private Long codigoGrupo;
    private String nomeGrupo;
    private String sistema;
    
    @Autowired
    private GrupoUsuarioService grupoUsuarioService;
    
    @Autowired
    private DireitoUsuarioService direitoUsuarioService;

    public String setup() {

        this.sistema = SistemaEnum.SICE.getValue();
        inicializar();

	return PaginaEnum.GRUPO_USUARIO.getValue();

    }
    
    public void inicializar() {
        
	this.usuariosSelecionados = null;
	this.grupoSelecionado = null;
	this.usuarioSelecionado = null;
	this.codigoGrupo = null;
	this.nomeGrupo = null;
	this.direitos = this.direitoUsuarioService.recuperarDireitosPorSistema(this.sistema);
	this.usuarioDataModel = new UsuarioDataModel(this.grupoUsuarioService.recuperarUsuariosDoSistema());
        
        List<GrupoUsuario> gruposUsuario = this.grupoUsuarioService.recuperarGruposUsuarioPorSistema(this.sistema);
        
        //Responsável Por Inicializar as Coleções de Direitos do Usuário
        //e Também As Permissões Associadas ao Grupo, Evitando Erro de
        //LazyInitializationException
        for (GrupoUsuario grupoUsuario : gruposUsuario) {
            for (DireitoUsuario direito : grupoUsuario.getDireitosUsuario()){}
            for (DireitoGrupoUsuario dgu : grupoUsuario.getDireitosGruposUsuarios()){}
        }
        
	this.grupoUsuarioDataModel = new GrupoUsuarioDataModel(gruposUsuario);
        
	this.direitosSistema = new DualListModel<DireitoSistema>(
		new ArrayList<DireitoSistema>(), new ArrayList<DireitoSistema>());
        
    }

    public String voltar() {

	return PaginaEnum.PAGINA_PRINCIPAL.getValue();

    }

    public void remover() {

        try {
            
            this.grupoUsuarioService.excluir(this.grupoUsuarioService.obterPorId(this.grupoSelecionado.getId()));
            MensagemUtil.exibirMensagemInformacao(MensagemUtil.getMensagem("grupoUsuarioExcluidoSucesso"));
            
            inicializar();
            
        } catch (Exception ex) {
            
            tratarExcessao(ex);
            
        }

    }

    public void aoSelecionarLinha() {

	if (this.grupoSelecionado != null) {
	    List<DireitoSistema> target = this.grupoUsuarioService.recuperarDireitosVinculadosAoGrupo(this.grupoSelecionado, this.sistema);
	    List<DireitoSistema> source = this.grupoUsuarioService.recuperarDireitosNotIn(target, this.sistema);
	    this.direitosSistema = new DualListModel<DireitoSistema>(source, target);
	} else {
	    this.direitosSistema = new DualListModel<DireitoSistema>(new ArrayList<DireitoSistema>(), new ArrayList<DireitoSistema>());
	}

    }

    public void salvar() throws Exception{

	for (GrupoUsuario grupo : this.grupoUsuarioDataModel.getGruposUsuario()) {
	    this.grupoUsuarioService.atualizar(grupo);
	}

	if (this.grupoSelecionado != null) {
	    this.grupoUsuarioService.salvarAtualizarDireitosGrupo(
		    this.grupoSelecionado, this.direitosSistema.getTarget());
	}

	MensagemUtil.exibirMensagemInformacao(MensagemUtil.getMensagem("registro_salvo_sucesso"));

	inicializar();

    }

    public String adicionarGrupoUsuario() throws Exception{

	if (this.grupoUsuarioService.isGrupoJaCadastrado(this.codigoGrupo, this.sistema)) {
	    MensagemUtil.exibirMensagemAlerta(MensagemUtil.getMensagem("grupoUsuarioGrupoJaCadastradoCodigo"));
	    return null;
	}

	if (this.grupoUsuarioService.isGrupoJaCadastrado(this.nomeGrupo, this.sistema)) {
	    MensagemUtil.exibirMensagemAlerta(MensagemUtil.getMensagem("grupoUsuarioGrupoJaCadastradoNome"));
	    return null;
	}

	GrupoUsuario grupo = new GrupoUsuario();
	
        grupo.setId(this.codigoGrupo);
	grupo.setNome(this.nomeGrupo);
        grupo.setSistema(this.sistema);

	this.grupoUsuarioService.salvar(grupo);
	
        inicializar();
	
	MensagemUtil.exibirMensagemInformacao(MensagemUtil.getMensagem("grupoUsuarioAdicionadoComSucesso"));

	return null;

    }

    public void limparDadosGrupo() {

	this.codigoGrupo = null;
	this.nomeGrupo = null;

    }

    public void configurarUsuariosAdicionados() {

	List<Usuario> usuarios = new ArrayList<Usuario>();
	for (DireitoUsuario direitoUsuario : this.grupoSelecionado.getDireitosUsuario()) {
	    usuarios.add(direitoUsuario.getUsuario());
	}
	this.usuariosSelecionados = usuarios.toArray(new Usuario[usuarios.size()]);

    }

    public void adicionarUsuariosSelecionadosAoGrupo() {

	List<Usuario> usuarios = Arrays.asList(this.usuariosSelecionados);
	this.grupoSelecionado.getDireitosUsuario().clear();

	Iterator<DireitoUsuario> iterator = this.grupoSelecionado.getDireitosUsuario().iterator();

	while (iterator.hasNext()) {
	    if (!usuarios.contains(iterator.next().getUsuario())) {
		iterator.remove();
	    }
	}

	for (Usuario usuario : usuarios) {
	    if (!this.grupoSelecionado.contemUsuario(usuario)) {
		DireitoUsuario direitoUsuario = new DireitoUsuario();
		direitoUsuario.setUsuario(usuario);
		direitoUsuario.setGrupo(this.grupoSelecionado);
		this.grupoSelecionado.getDireitosUsuario().add(direitoUsuario);
	    }
	}

    }

    // <editor-fold desc="GETTERS AND SETTERS" defaultstate="collapsed">           
    public List<DireitoSistema> getDireitos() {
	return direitos;
    }

    public void setDireitos(List<DireitoSistema> direitos) {
	this.direitos = direitos;
    }

    public GrupoUsuarioDataModel getGrupoUsuarioDataModel() {
	return grupoUsuarioDataModel;
    }

    public void setGrupoUsuarioDataModel(GrupoUsuarioDataModel grupoUsuarioDataModel) {
	this.grupoUsuarioDataModel = grupoUsuarioDataModel;
    }

    public DualListModel<DireitoSistema> getDireitosSistema() {
	return direitosSistema;
    }

    public void setDireitosSistema(DualListModel<DireitoSistema> direitosSistema) {
	this.direitosSistema = direitosSistema;
    }

    public GrupoUsuario getGrupoSelecionado() {
	return grupoSelecionado;
    }

    public void setGrupoSelecionado(GrupoUsuario grupoSelecionado) {
	this.grupoSelecionado = grupoSelecionado;
    }

    public Long getCodigoGrupo() {
	return codigoGrupo;
    }

    public void setCodigoGrupo(Long codigoGrupo) {
	this.codigoGrupo = codigoGrupo;
    }

    public String getNomeGrupo() {
	return nomeGrupo;
    }

    public void setNomeGrupo(String nomeGrupo) {
	this.nomeGrupo = nomeGrupo;
    }

    public UsuarioDataModel getUsuarioDataModel() {
	return usuarioDataModel;
    }

    public void setUsuarioDataModel(UsuarioDataModel usuarioDataModel) {
	this.usuarioDataModel = usuarioDataModel;
    }

    public Usuario getUsuarioSelecionado() {
	return usuarioSelecionado;
    }

    public void setUsuarioSelecionado(Usuario usuarioSelecionado) {
	this.usuarioSelecionado = usuarioSelecionado;
    }

    public Usuario[] getUsuariosSelecionados() {
	return usuariosSelecionados;
    }

    public void setUsuariosSelecionados(Usuario[] usuariosSelecionados) {
	this.usuariosSelecionados = usuariosSelecionados;
    }

    public String getSistema() {
        return sistema;
    }
    
    public String getSistemaStr() {
        return this.sistema != null ? SistemaEnum.getDescricao(this.sistema) : null;
    }

    public void setSistema(String sistema) {
        this.sistema = sistema;
    }  
    
    public List<SelectItem> getSistemas() {
        return obterSelectItemPopulado(false, SistemaEnum.values());
    }
    // </editor-fold>

    // <editor-fold desc="DATA MODEL DE GRUPOS DE USUÁRIOS" defaultstate="collapsed">               
    public class GrupoUsuarioDataModel extends ListDataModel<GrupoUsuario> implements SelectableDataModel<GrupoUsuario>, Serializable {

	public GrupoUsuarioDataModel() {
	}

	public GrupoUsuarioDataModel(List<GrupoUsuario> list) {
	    super(list);
	}

	@Override
	public Object getRowKey(GrupoUsuario grupoUsuario) {
	    return grupoUsuario.getId();
	}

	@Override
	public GrupoUsuario getRowData(String idGrupoUsuario) {
	    List<GrupoUsuario> grupos = (List<GrupoUsuario>) getWrappedData();
	    for (GrupoUsuario grupo : grupos) {
		if (grupo.getId().equals(Long.parseLong(idGrupoUsuario))) {
		    return grupo;
		}
	    }
	    return null;
	}

	public List<GrupoUsuario> getGruposUsuario() {
	    return (List<GrupoUsuario>) getWrappedData();
	}
    }
    // </editor-fold>    

    // <editor-fold desc="DATA MODEL DE USUÁRIOS" defaultstate="collapsed">                   
    public class UsuarioDataModel extends ListDataModel<Usuario> implements SelectableDataModel<Usuario>, Serializable {

	public UsuarioDataModel() {
	}

	public UsuarioDataModel(List<Usuario> list) {
	    super(list);
	}

	@Override
	public Object getRowKey(Usuario usuario) {
	    return usuario.getId();
	}

	@Override
	public Usuario getRowData(String idUsuario) {
	    List<Usuario> usuarios = (List<Usuario>) getWrappedData();
	    for (Usuario usuario : usuarios) {
		if (usuario.getId().toString().equals(idUsuario)) {
		    return usuario;
		}
	    }
	    return null;
	}

	public List<Usuario> getUsuarios() {
	    return (List<Usuario>) getWrappedData();
	}
    }
    // </editor-fold>  
    
}
